home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Applications / DockExtenders / LaunchPad / Source / Controller.m < prev    next >
Text File  |  1994-05-10  |  30KB  |  1,267 lines

  1.  
  2. // Controller.m
  3.  
  4. /*
  5.  * Copyright 1991 RightBrain Software.  All rights reserved.
  6.  *
  7.  * No part of this code may be reproduced in any form, compiled
  8.  * or source code, nor used for any purpose without the express
  9.  * written permission of RightBrain Software.
  10.  * 
  11.  * Entered into the public domain 12/15/93 by RightBrain Software.
  12.  *
  13.  */
  14. #import <libc.h>
  15. #import <strings.h>
  16. #import <time.h>
  17. #import <math.h>
  18. #import <sys/types.h>
  19. #import <sys/stat.h>
  20. #import <streams/streams.h>
  21. #import <objc/objc-load.h>
  22. #import <objc/NXStringTable.h>
  23. #import <dpsclient/psops.h>
  24. #import <dpsclient/wraps.h>
  25. #import <defaults/defaults.h>
  26. #import <appkit/publicWraps.h>
  27. #import <appkit/TextField.h>
  28. #import <appkit/View.h>
  29. #import <appkit/Window.h>
  30. #import <appkit/Panel.h>
  31. #import <appkit/Listener.h>
  32. #import <appkit/Speaker.h>
  33. #import <appkit/Application.h>
  34. #import <appkit/ScrollView.h>
  35. #import <appkit/OpenPanel.h>
  36. #import <appkit/SavePanel.h>
  37. #import <appkit/Button.h>
  38. #import <appkit/Text.h>
  39. #import <appkit/ButtonCell.h>
  40. #import <appkit/Font.h>
  41. #import <objc/List.h>
  42.  
  43. #import "MyPanel.h"
  44. #import "InfoPanel.h"
  45. #import "timebomb.h"
  46.  
  47. #define NO_VIEWER 0
  48. #define TIFF_VIEWER 1
  49. #define TEXT_VIEWER 2
  50. #define EPS_VIEWER 3
  51.  
  52. #define ICON_DELTA 54.0
  53.  
  54. #import "IconView.h"
  55. #import "Controller.h"
  56. #import "CopyIcon.h"
  57.  
  58. id    theClass;
  59.  
  60. @implementation Controller
  61.  
  62.  
  63. /****************************** appDidInit */
  64. - appDidInit:sender
  65. {
  66.     unsigned int    windowNum;
  67.     const char        *defaultValue;
  68.     id            speaker;
  69.     FILE        *fd, *tmp;
  70. //    int            response;
  71.     NXRect onScreen =  {{874.0,310.0},{172.0,301.0}};
  72.     NXRect offScreen = {{1300.0,-1200.0},{72.0,72.0}};
  73.     
  74.     [NXApp loadNibSection: "InfoPanel.nib" owner: self withNames:YES];
  75.     #if TIME_BOMB_VERSION
  76.     [infoPanel timeBombCheck];
  77.     #endif
  78.     [infoPanel setupVersionText];
  79.     [infoPanel checkRegistration:self];
  80.  
  81. //    defaults = [Defaults new];
  82.     
  83.   // open panel and promote panel to front
  84.     [NXApp loadNibSection:"Panel.nib" owner:self withNames:NO];
  85.     [dragPanel orderOut:self];
  86.     [dragPanel placeWindow:&offScreen];
  87.     [dragPanel makeKeyAndOrderFront:self];
  88.     [dragPanel orderOut:self];
  89.     [dragPanel placeWindow:&onScreen];
  90.     [dragPanel setDelegate:self];
  91.  
  92.   // register our app icon window with the workspace
  93.     NXConvertWinNumToGlobal([dragPanel windowNum], &windowNum);
  94.     myWindowNum = windowNum;
  95.     speaker = [NXApp appSpeaker];
  96.     [speaker setSendPort:NXPortFromName(NX_WORKSPACEREQUEST, NULL)];
  97.     [speaker registerWindow:windowNum
  98.              toPort:[[NXApp appListener] listenPort]];
  99.     
  100.     iconList = [[List alloc] initCount:100];
  101.     [[scroller docView] setAutoresizeSubviews:YES];
  102.     iconCount = 0;
  103.     selected = NULL;
  104.  
  105.     sprintf ( listFileName, "/bin/mkdirs %s/.RightBrain", NXHomeDirectory() );
  106.     system ( listFileName );
  107.     sprintf ( listFileName, "%s/.RightBrain/launchList", NXHomeDirectory() );
  108.  
  109.     fd = fopen ( listFileName, "r" );
  110.     if ( !fd ) {
  111.     /***
  112.     response = NXRunAlertPanel ( "No File",
  113.         "Can't find %s",
  114.         "Continue", "Quit", NULL, listFileName
  115.     );
  116.     if ( response != NX_ALERTDEFAULT ) {
  117.         [NXApp terminate:self];
  118.         exit(1);
  119.     }
  120.     ***/
  121.     sprintf ( buff, "cp %s %s.bak", listFileName, listFileName );
  122.     system ( buff );
  123.     fd = fopen ( listFileName, "w" );
  124.     if ( fd ) {
  125.         fprintf ( fd, "#window: 874.00 310.00 172.00 301.00\n" );
  126.  
  127.         // check for LockScreen and install if you find it
  128.         sprintf ( buff,
  129.         "%s/Apps/LockScreen.app/LockScreen", NXHomeDirectory
  130.         );
  131.         tmp = fopen ( buff, "r" );
  132.         if ( tmp ) {
  133.         sprintf ( buff,
  134.             "X%s/Apps/LockScreen.app\n", NXHomeDirectory
  135.         );
  136.         fprintf ( fd, buff );
  137.         fclose ( tmp );
  138.         } else {
  139.         tmp = fopen ( "/LocalApps/LockScreen.app/LockScreen", "r" );
  140.         if ( tmp ) {
  141.             fprintf ( fd, "X/LocalApps/LockScreen.app\n" );
  142.             fclose ( tmp );
  143.         }
  144.         }
  145.         // check for Rulers and install if you find it
  146.         sprintf ( buff,
  147.         "%s/Apps/Rulers", NXHomeDirectory
  148.         );
  149.         tmp = fopen ( buff, "r" );
  150.         if ( tmp ) {
  151.         sprintf ( buff,
  152.             "X%s/Apps/Rulers\n", NXHomeDirectory
  153.         );
  154.         fprintf ( fd, buff );
  155.         fclose ( tmp );
  156.         } else {
  157.         tmp = fopen ( "/LocalApps/Rulers", "r" );
  158.         if ( tmp ) {
  159.             fprintf ( fd, "X/LocalApps/Rulers\n" );
  160.             fclose ( tmp );
  161.         }
  162.         }
  163.         // check for Portfolio and install if you find it
  164.         sprintf ( buff,
  165.         "%s/Apps/Portfolio", NXHomeDirectory
  166.         );
  167.         tmp = fopen ( buff, "r" );
  168.         if ( tmp ) {
  169.         sprintf ( buff,
  170.             "X%s/Apps/Portfolio\n", NXHomeDirectory
  171.         );
  172.         fprintf ( fd, buff );
  173.         fclose ( tmp );
  174.         } else {
  175.         tmp = fopen ( "/LocalApps/Portfolio", "r" );
  176.         if ( tmp ) {
  177.             fprintf ( fd, "X/LocalApps/Portfolio\n" );
  178.             fclose ( tmp );
  179.         }
  180.         }
  181.         // check for TypeView and install if you find it
  182.         sprintf ( buff,
  183.         "%s/Apps/TypeView.app/TypeView", NXHomeDirectory
  184.         );
  185.         tmp = fopen ( buff, "r" );
  186.         if ( tmp ) {
  187.         sprintf ( buff,
  188.             "X%s/Apps/TypeView.app\n", NXHomeDirectory
  189.         );
  190.         fprintf ( fd, buff );
  191.         fclose ( tmp );
  192.         } else {
  193.         tmp = fopen ( "/LocalApps/TypeView.app/TypeView", "r" );
  194.         if ( tmp ) {
  195.             fprintf ( fd, "X/LocalApps/TypeView.app\n" );
  196.             fclose ( tmp );
  197.         }
  198.         }
  199.         // check for PasteUp and install if you find it
  200.         sprintf ( buff,
  201.         "%s/Apps/PasteUp.app/PasteUp", NXHomeDirectory
  202.         );
  203.         tmp = fopen ( buff, "r" );
  204.         if ( tmp ) {
  205.         sprintf ( buff,
  206.             "X%s/Apps/PasteUp.app\n", NXHomeDirectory
  207.         );
  208.         fprintf ( fd, buff );
  209.         fclose ( tmp );
  210.         } else {
  211.         tmp = fopen ( "/LocalApps/PasteUp.app/PasteUp", "r" );
  212.         if ( tmp ) {
  213.             fprintf ( fd, "X/LocalApps/PasteUp.app\n" );
  214.             fclose ( tmp );
  215.         }
  216.         }
  217.         fclose ( fd );
  218.     }
  219.     } else {
  220.     fclose ( fd );
  221.     }
  222.     [self readFileList:listFileName];
  223.     [dragPanel makeKeyAndOrderFront:self];
  224.     // [dragPanel setFloatingPanel:YES];
  225.     // PSsetwindowlevel(MAXINT-1, [dragPanel windowNum]);
  226.     
  227.     // auto-launch files as appropriate:
  228.     defaultValue = NXGetDefaultValue("LaunchPad", "NXAutoLaunch");
  229.     if ( defaultValue ) {
  230.     if (*defaultValue == 'Y') {
  231.         [NXApp deactivateSelf];
  232.         [self launchAll:self];
  233.         /***
  234.         if ( iconCount ) {
  235.         [NXApp hide:self];
  236.         }
  237.         ***/
  238.     }
  239.     }
  240.     [self setFrom:NULL];
  241.  
  242.     return self;
  243. }
  244.  
  245. - appDidUnhide:sender;
  246. {
  247.     [self displayDock:self];
  248.     return self;
  249. }
  250.  
  251. - appDidBecomeActive:sender;
  252. {
  253.     [self displayDock:self];
  254.     return self;
  255. }
  256.  
  257.  
  258. - new:sender
  259. {
  260.     id document;
  261.  
  262.     document = [[MyPanel alloc] init];
  263.     [NXApp loadNibSection:"Panel.nib" owner:self withNames:NO];
  264.     [document makeKeyAndOrderFront:self];
  265.     return self;
  266. }
  267.  
  268.  
  269. - (char *)listFileName;
  270. {
  271.     return listFileName;
  272. }
  273.  
  274.  
  275. - defaults;
  276. {
  277.     return defaults;
  278. }
  279.  
  280.  
  281. - (float) widestName {
  282.     return widestName;
  283. }
  284.  
  285.  
  286. - gimmeScroller;
  287. {
  288.     return scroller;
  289. }
  290.  
  291.  
  292. - stringTable;
  293. {
  294.     return stringTable;
  295. }
  296.  
  297. - launchAll:sender;
  298. {
  299.     int response, idx;
  300.     id file;
  301.     
  302.     if ( sender != self ) {
  303.     response = NXRunAlertPanel (
  304.         [stringTable valueForStringKey:"launch"],
  305.         "%s",
  306.         [stringTable valueForStringKey:"launchAll"],
  307.         [stringTable valueForStringKey:"launchChecked"],
  308.         [stringTable valueForStringKey:"cancel"],
  309.         [stringTable valueForStringKey:"reallyLaunch"]
  310.     );
  311.     if ( response == NX_ALERTDEFAULT ) {
  312.         for ( idx=0; idx < [iconList count]; idx++ ) {
  313.         file = [iconList objectAt:idx];
  314.         [file openSelf:sender];
  315.         }
  316.     } else if ( response == NX_ALERTALTERNATE ) {
  317.         for ( idx=0; idx < [iconList count]; idx++ ) {
  318.         file = [iconList objectAt:idx];
  319.         [file openSelfIfAutoLaunch:sender];
  320.         }
  321.     } else {
  322.         return self;
  323.     }
  324.     } else {
  325.     for ( idx=0; idx < [iconList count]; idx++ ) {
  326.         file = [iconList objectAt:idx];
  327.         [file openSelfIfAutoLaunch:sender];
  328.     }
  329.     }
  330.     return self;
  331. }
  332.  
  333.  
  334. #define OPEN 1
  335. #define SAVE 2
  336. - (const char *)getFile: (int)openOrClose;
  337. {
  338.     const char *types[2];
  339.     const char *mydirectory;
  340.     char inputfile[FILENAME_MAX];
  341.     const char *const *files;
  342.     int result;
  343.     id openpanel;
  344.  
  345.     if ( openOrClose == SAVE ) {
  346.     openpanel = [OpenPanel new];
  347.     } else {
  348.     openpanel = [SavePanel new];
  349.     }
  350.     if ( !mydirectory ) mydirectory = NXHomeDirectory();
  351.     inputfile[0] = '\0';
  352.     types[0] = "drag";
  353.     types[1] = NULL;
  354.     if ( openOrClose == SAVE ) {
  355.     [openpanel setRequiredFileType: ".drag"];
  356.     result = [openpanel runModalForDirectory:mydirectory
  357.             file:inputfile types:types];
  358.     } else {
  359.     result = [openpanel runModalForDirectory:mydirectory
  360.             file:inputfile types:types];
  361.     }
  362.     if ( result ) {
  363.     files = [openpanel filenames];
  364.     sprintf ( inputfile, "%s/%s", [openpanel directory], *files );
  365.     return inputfile;
  366.     }
  367.     return NULL;
  368. }
  369.  
  370.  
  371. - selected;
  372. {
  373.     selected = iconView;
  374.     return selected;
  375. }
  376.  
  377. - setSelected:which;
  378. {
  379.     selected = which;
  380.     iconView = which;
  381.     return self;
  382. }
  383.  
  384. - fromWhich;
  385. {
  386.     return fromWhich;
  387. }
  388.  
  389. - setFrom:which;
  390. {
  391.     fromWhich = which;
  392.     return self;
  393. }
  394.  
  395.  
  396. - cut:sender;
  397. {
  398.     int response;
  399.     const char *fname, *tab;
  400.     
  401.     if ( iconView && [iconView filename] && strlen([iconView filename]) ) {
  402.     fname = [iconView filename];
  403.     tab = index ( fname, '\t' );
  404.     if ( tab ) {
  405.         fname = [stringTable valueForStringKey:"fileCollection"];
  406.     } else {
  407.         fname = (const char *)(rindex([iconView filename], '/') + 1);
  408.     }
  409.     response = NXRunAlertPanel (
  410.         [stringTable valueForStringKey:"Cut"],
  411.         "%s %s ?",
  412.         [stringTable valueForStringKey:"OK"],
  413.         [stringTable valueForStringKey:"cancel"], NULL,
  414.         [stringTable valueForStringKey:"remove"],
  415.         fname
  416.     );
  417.     if ( response != NX_ALERTDEFAULT ) return self;
  418.     
  419.     [self removeFileFromScroller:[iconView filename]];
  420.     } else {
  421.     NXBeep();
  422.     }
  423.     return self;
  424. }
  425.  
  426.  
  427. - clearList:sender;
  428. {
  429.     int idx;
  430.     const char *filename;
  431.     
  432.     for ( idx=0; idx < [iconList count]; idx++ ) {
  433.     filename = [[iconList objectAt:idx] filename];
  434.     if ( filename && strlen(filename) ) {
  435.         [self removeFileFromScroller:filename];
  436.     }
  437.     }
  438.     return self;
  439. }
  440.  
  441.  
  442. - openList:sender;
  443. {
  444.     const char *filename;
  445.     
  446.     filename = [self getFile:OPEN];
  447.     if ( filename ) {
  448.     [self clearList:self];
  449.     [self readFileList:filename];
  450.     }
  451.     return self;
  452. }
  453.  
  454.  
  455. - addList:sender;
  456. {
  457.     const char *filename;
  458.     
  459.     filename = [self getFile:OPEN];
  460.     if ( filename ) {
  461.     [self readFileList:filename];
  462.     }
  463.     return self;
  464. }
  465.  
  466.  
  467. - newList:sender;
  468. {
  469.     int result;
  470.     result = NXRunAlertPanel (
  471.     [stringTable valueForStringKey:"alert"],
  472.     "%s",
  473.     [stringTable valueForStringKey:"OK"],
  474.     [stringTable valueForStringKey:"cancel"], NULL,
  475.     [stringTable valueForStringKey:"reallyToss"]
  476.     );
  477.     if ( result == NX_ALERTDEFAULT ) {
  478.     [self clearList:self];
  479.     }
  480.     return self;
  481. }
  482.  
  483.  
  484. - saveList:sender;
  485. {
  486.     const char *filename;
  487.     
  488.     filename = [self getFile:SAVE];
  489.     if ( filename ) {
  490.     [self writeFileList:filename];
  491.     }
  492.     return self;
  493. }
  494.  
  495.  
  496. - saveAsList:sender;
  497. {
  498.     const char *filename;
  499.     
  500.     filename = [self getFile:SAVE];
  501.     if ( filename ) {
  502.     [self writeFileList:filename];
  503.     }
  504.     return self;
  505. }
  506.  
  507.  
  508. - writeFileList: (const char *)fname;
  509. {
  510.     FILE *fd;
  511.     int idx;
  512.     const char *filename;
  513.     NXRect winRect;
  514.  
  515.     [dragPanel getPosition:&winRect];
  516.     if ( winRect.size.width <= 0.0 ) {
  517.     return self;
  518.     }
  519.     sprintf ( buff, "cp %s %s.bak", fname, fname );
  520.     system ( buff );
  521.     fd = fopen ( fname, "w" );
  522.     if ( fd ) {
  523.     fprintf ( fd,
  524.         "#window: %3.2f %3.2f %3.2f %3.2f\n",
  525.         winRect.origin.x, winRect.origin.y,
  526.         winRect.size.width, winRect.size.height
  527.     );
  528.     for ( idx=0; idx < [iconList count]; idx++ ) {
  529.         filename = [[iconList objectAt:idx] filename];
  530.         if ( [[iconList objectAt:idx] autoLaunch] ) {
  531.         fprintf ( fd, "X" );
  532.         }
  533.         if ( filename && strlen(filename) ) {
  534.         fprintf ( fd, "%s\n", filename );
  535.         }
  536.     }
  537.     fclose ( fd );
  538.     } else {
  539.     sprintf ( buff, "cp %s.bak %s", fname, fname );
  540.     fprintf ( stderr, "couldn't open; restoring %s\n", fname );
  541.     system ( buff );
  542.     }
  543.     return self;
  544. }
  545.  
  546.  
  547. - readFileList: (const char *)fname;
  548. {
  549.     FILE *fd;
  550.     char *bytes, dummy[30], *tabChar;
  551.     int morefiles, multiple;
  552.     float f1, f2, f3, f4;
  553.     NXRect pos;
  554.  
  555.     fd = fopen ( fname, "r" );
  556.     if ( fd ) {
  557.     bytes = fgets ( buff, 1024, fd );
  558.     if ( buff[0] != '#' ) {
  559.         if ( buff[0] == '/' ) {
  560.         buff[strlen(buff)-1] = '\0';
  561.         tabChar = index ( buff, '\t' );
  562.         multiple = (tabChar != NULL);
  563.         [self addFileToScroller:buff:multiple:0];
  564.         filePath = (char *)[[iconList lastObject] filename];
  565.         [self setFileIconFor:[iconList lastObject]:filePath];
  566.         [dragPanel makeKeyAndOrderFront:self];
  567.         }
  568.     } else {
  569.         sscanf ( buff, "%s %f %f %f %f", dummy, &f1, &f2, &f3, &f4 );
  570.         if ( (f3 > 20.0) && (f4 > 20.0) ) {
  571.         pos.origin.x = f1;
  572.         pos.origin.y = f2;
  573.         pos.size.width = f3;
  574.         pos.size.height = f4;
  575.         [dragPanel setPosition:&pos];
  576.         }
  577.         [dragPanel makeKeyAndOrderFront:self];
  578.     }
  579.     morefiles = YES;
  580.     while ( morefiles ) {
  581.         bytes = fgets ( buff, 1024, fd );
  582.         if ( bytes ) {
  583.         if ( strncmp(buff,"window",6) ) {
  584.             if ( buff[0] == '\n' ) {
  585.             continue;
  586.             }
  587.             if ( (buff[0] != '/') && (buff[0] != 'X') ) {
  588.             continue;
  589.             }
  590.             buff[strlen(buff)-1] = '\0';
  591.             tabChar = index ( buff, '\t' );
  592.             multiple = (tabChar != NULL);
  593.             [self addFileToScroller:buff:multiple:0];
  594.             filePath = (char *)[[iconList lastObject] filename];
  595.             [self setFileIconFor:[iconList lastObject]:filePath];
  596.         }
  597.         } else {
  598.         morefiles = NO;
  599.         }
  600.     }
  601.     fclose ( fd );
  602.     filePath = NULL; // (char *)[[iconList lastObject] filename];
  603.     iconView = [iconList lastObject];
  604.     selected = iconView;
  605.     }
  606.     return self;
  607. }
  608.  
  609.  
  610. - moveIconInScroller: theIcon by:(float)dX : (float)dY;
  611. {
  612.     [theIcon moveBy: dX : dY];
  613.     [[theIcon myCheckBox] moveBy: dX : dY];
  614.     [[theIcon myWideBox] moveBy: dX : dY];
  615.     [[theIcon myLabelText] moveBy: dX : dY];
  616.     [[theIcon myDirText] moveBy: dX : dY];
  617.     return self;
  618. }
  619.  
  620.  
  621. - slideIconInScroller: theIcon toLocation:(float)toY;
  622. {
  623.     int idx, ix, newPosition, oldPosition;
  624.     // const char    *nameFromList;
  625.     id        movingIcon;
  626.     NXPoint    releasePoint;
  627.     
  628.     oldPosition = 0;
  629.     for ( idx=0; idx < [iconList count]; idx++ ) {
  630.     if ( [iconList objectAt:idx] == theIcon ) {
  631.         oldPosition = idx;
  632.         break;
  633.     }
  634.     }
  635.     releasePoint.x = 24.0;  releasePoint.y = toY;
  636.     // [dragPanel convertScreenToBase:&releasePoint];
  637.     [[dragPanel contentView] convertPoint:&releasePoint
  638.     toView:[scroller docView]
  639.     ];
  640.     newPosition = (int)(releasePoint.y / ICON_DELTA);
  641.     if ( newPosition >= [iconList count] ) {
  642.     newPosition = [iconList count] - 1;
  643.     }
  644.     if ( newPosition < 0) newPosition = 0;
  645.     if ( newPosition != oldPosition ) {
  646.     [self moveIconInScroller: iconView
  647.         by:0.0:(ICON_DELTA*(newPosition-oldPosition))
  648.     ];
  649.     // remove old icon:
  650.     for ( ix=idx+1; ix < [iconList count]; ix++ ) {
  651.         movingIcon = [iconList objectAt:ix];
  652.         [self moveIconInScroller: movingIcon by:0.0:ICON_DELTA * -1];
  653.     }
  654.     [iconList removeObjectAt:idx];
  655.     // add new one:
  656.     for ( ix=newPosition; ix < [iconList count]; ix++ ) {
  657.         movingIcon = [iconList objectAt:ix];
  658.         [self moveIconInScroller: movingIcon by:0.0:ICON_DELTA];
  659.     }
  660.     [iconList insertObject: iconView at:newPosition];
  661.     [[scroller docView] display];
  662.     }
  663.     [self writeFileList:listFileName];
  664.     return self;
  665. }
  666.  
  667.  
  668. - removeFileFromScroller: (const char *)fname;
  669. {
  670.     id tmp, newSelected;
  671.     int idx, location;
  672.     const char *filename;
  673.  
  674.     location = 0;
  675.     if ( fname == NULL ) {
  676.     // remove the current object
  677.     filename = [iconView filename];
  678.     location = [iconList indexOf:iconView];
  679.     } else {
  680.     for ( idx=0; idx < [iconList count]; idx++ ) {
  681.         tmp = [iconList objectAt:idx];
  682.         filename = [tmp filename];
  683.         if ( !strcmp ( fname, filename ) ) {
  684.         iconView = tmp;
  685.         location = idx;
  686.         break;
  687.         }
  688.     }
  689.     }
  690.     [iconList removeObject:iconView];
  691.     iconCount--;
  692.     [iconView removeFromSuperview];
  693.     [[[iconView myCheckBox] removeFromSuperview] free];
  694.     [[[iconView myWideBox]  removeFromSuperview] free];
  695.     [[[iconView myLabelText] removeFromSuperview] free];
  696.     [[[iconView myDirText] removeFromSuperview] free];
  697.     for ( idx=location; idx < [iconList count]; idx++ ) {
  698.     tmp = [iconList objectAt:idx];
  699.     [self moveIconInScroller: tmp by:0.0:ICON_DELTA * -1];
  700.     }
  701.     [[scroller docView] sizeBy: 0 : -1 * ICON_DELTA];
  702.     [[scroller docView] display];
  703.     [dragPanel display];
  704.     NXPing();
  705.     [iconView free];
  706.     if ( location >= [iconList count] ) {
  707.     newSelected = [iconList lastObject];
  708.     } else {
  709.     newSelected = [iconList objectAt:location];
  710.     }
  711.     [[NXApp delegate] setSelected:newSelected];
  712.     [newSelected display];
  713.     [self writeFileList:listFileName];
  714.     return self;
  715. }
  716.  
  717.  
  718. - addFileToScroller: (char *)fname : (int)multiple : (int)winNum
  719. {
  720.     NXRect iconRect = {{0.0, 0.0}, {54.0, 54.0}};
  721.     NXRect textRect = {{0.0, 0.0}, {1000.0, 16.0}};
  722.     NXRect checkRect = {{0.0, 0.0}, {15.0, 15.0}};
  723.     NXRect scrollRect;
  724.     id       checkBox, wideBox, Xview, labelText, dirText;
  725.     char  *ptr;
  726.     int    isAuto;
  727.     float  width;
  728.  
  729.     if ( !fname ) return self;
  730.     if ( !strlen(fname) ) return self;
  731.     
  732.     ptr = fname;
  733.     if ( fname[0] == 'X' ) {
  734.     isAuto = YES;
  735.     ptr++;
  736.     } else {
  737.     isAuto = NO;
  738.     }
  739.  
  740.     iconView = [[IconView new] initFrame:&iconRect];
  741.     [iconView setFilename:ptr multipleSelected:multiple];
  742.     [iconList addObject:iconView];
  743.     iconCount++;
  744.     Xview = [scroller docView];
  745.     [Xview addSubview:iconView];
  746.     [iconView moveBy: 0 : ICON_DELTA*(iconCount-1)];
  747.     [Xview sizeBy: 0 : ICON_DELTA];
  748.     NXSetRect(&scrollRect, 0.0, ICON_DELTA*(iconCount-1), 54.0, 54.0);
  749.     [Xview scrollRectToVisible:&scrollRect];
  750.  
  751.     // add a check box
  752.     checkBox = [[Button new] initFrame: &checkRect
  753.     icon:"NXswitch"
  754.     tag:0
  755.     target:iconView
  756.     action:@selector(toggleCheckBox:)
  757.     key:(unsigned short)0
  758.     enabled:YES
  759.     ];
  760.     [checkBox setBordered:YES];
  761.     [checkBox setAltIcon:"NXswitchH"];
  762.     [checkBox setType:NX_TOGGLE];
  763.     if ( isAuto ) {
  764.     [checkBox setState: 1];
  765.     [iconView toggleCheckBox:self];
  766.     }
  767.     [Xview addSubview:checkBox];
  768.     [iconView setMyCheckBox:checkBox];
  769.     [checkBox moveBy: ICON_DELTA + 2 : ICON_DELTA*iconCount - 17.0];
  770.  
  771.     // add a resize box
  772.     wideBox = [[Button new] initFrame: &checkRect
  773.     icon:"makeWideIcon"
  774.     tag:-1
  775.     target:self
  776.     action:@selector(toggleFromButton:)
  777.     key:(unsigned short)0
  778.     enabled:YES
  779.     ];
  780.     [wideBox setBordered:NO];
  781.     [wideBox setAltIcon:"makeWideIcon"];
  782.     [wideBox setType:NX_TOGGLE];
  783.     [Xview addSubview:wideBox];
  784.     [iconView setMyWideBox:wideBox];
  785.     [wideBox moveBy: ICON_DELTA + 2 : ICON_DELTA*(iconCount-1) + 2.0];
  786.  
  787.     // add the file name
  788.     labelText = [[Text new]
  789.     initFrame:&textRect
  790.     text:(const char *)[iconView appname]
  791.     alignment:NX_LEFTALIGNED
  792.     ];
  793.     [labelText setBackgroundGray:NX_LTGRAY];
  794.     [labelText setEditable:NO];
  795.     [labelText setSelectable:NO];
  796.     [labelText setOpaque:YES];
  797.     width = [[labelText font] getWidthOf:[iconView appname]];
  798.     if ( width > widestName ) {
  799.     widestName = width;
  800.     }
  801.     [Xview addSubview:labelText];
  802.     [labelText moveBy: ICON_DELTA + 20 : ICON_DELTA*iconCount - 17.0];
  803.     [iconView setMyLabelText:labelText];
  804.  
  805.     // add the directory name
  806.     sprintf ( buff, "(in %s)", [iconView dirname] );
  807.     dirText = [[Text new]
  808.     initFrame:&textRect
  809.     text:(const char *)[iconView dirname]
  810.     alignment:NX_LEFTALIGNED
  811.     ];
  812.     [dirText setText:buff];
  813.     [dirText setBackgroundGray:NX_LTGRAY];
  814.     [dirText setEditable:NO];
  815.     [dirText setSelectable:NO];
  816.     [dirText setOpaque:YES];
  817.     // add 9 to the width because directory name is shifted right 9 points
  818.     width = [[dirText font] getWidthOf:[iconView dirname]] + 15;
  819.     if ( width > widestName ) {
  820.     widestName = width;
  821.     }
  822.     [Xview addSubview:dirText];
  823.     [dirText moveBy: ICON_DELTA + 30 : ICON_DELTA*iconCount - 32.0];
  824.     [iconView setMyDirText:dirText];
  825.     
  826.     [Xview display];
  827.  
  828.     return self;
  829. }
  830.  
  831.  
  832. - setFileIconFor : theView : (char *)fname;
  833. {
  834.     id        speaker;
  835.     char    *application, *fileType;
  836.     int        anIlk, flag;
  837.     char    *tiff;
  838.     int        okFlag, length;
  839.     FILE    *fd;
  840.     int        rfd;
  841.     char    tmpFile [ 128 ];
  842.  
  843.   /* ask the Workspace for information about the file */
  844.     if ( fname && strlen(fname) && theView ) {
  845.     speaker = [NXApp appSpeaker];
  846.     [speaker setSendPort:NXPortFromName(NX_WORKSPACEREQUEST, NULL)];
  847.     [speaker getFileInfoFor: fname
  848.             app:&application
  849.             type:&fileType
  850.             ilk:&anIlk
  851.             ok:&flag];
  852.     if ( flag ) {
  853.         [theView setAppOrFile:anIlk];
  854.     } else {
  855.         [theView setAppOrFile:MISSING_FILE];
  856.     }
  857.     [speaker getFileIconFor: fname
  858.         TIFF: &tiff
  859.         TIFFLength: &length
  860.         ok: &okFlag
  861.     ];
  862.     if ( okFlag ) {
  863.         strcpy ( tmpFile, "/tmp/launchTMP123456.tiff" );
  864.         NXGetTempFilename(tmpFile, 14);
  865.         fd = fopen ( tmpFile, "w" );
  866.         if ( fd ) {
  867.         rfd = fileno ( fd );
  868.         write ( rfd, tiff, length );
  869.         close ( rfd );
  870.         [theView takeIconFromTIFF:tmpFile];
  871.         [theView display];
  872.         unlink ( tmpFile );
  873.         }
  874.     } else {
  875.         /*
  876.          * to get the "?" icon, create a symbolic link then
  877.          * delete the thing that the link points to, and then
  878.          * ask for the icon for the link.  What a hack.
  879.          */
  880.         fopen ( "/tmp/bogus", "w" );
  881.         system ( "ln -s /tmp/bogus /tmp/totally" );
  882.         unlink ( "/tmp/bogus" );
  883.         [speaker getFileIconFor: "/tmp/totally"
  884.         TIFF: &tiff
  885.         TIFFLength: &length
  886.         ok: &okFlag
  887.         ];
  888.         if ( okFlag ) {
  889.         strcpy ( tmpFile, "/tmp/launchTMP123456.tiff" );
  890.         NXGetTempFilename(tmpFile, 14);
  891.         fd = fopen ( tmpFile, "w" );
  892.         if ( fd ) {
  893.             rfd = fileno ( fd );
  894.             write ( rfd, tiff, length );
  895.             close ( rfd );
  896.             [theView takeIconFromTIFF:tmpFile];
  897.             // [theView display];
  898.             unlink ( tmpFile );
  899.         }
  900.         }
  901.         unlink ( "/tmp/totally" );
  902.         [theView setAppOrFile:MISSING_FILE];
  903.     }
  904.     }
  905.     return self;
  906. }
  907.  
  908.  
  909. - (int)iconEntered:(int)windowNum at:(double)x :(double)y
  910.     iconWindow:(int)iconWindowNum iconX:(double)iconX iconY:(double)iconY
  911.     iconWidth:(double)iconWidth iconHeight:(double)iconHeight
  912.     pathList:(char *)pathList
  913. {
  914.     char    *stringPosition;
  915.     const char    *nameFromList;
  916.     int        length, files=1;
  917.     int        idx;
  918.     
  919.   /* save the file's path for later */
  920.     length = strlen(pathList);
  921.     if (filePathLength <= length) {
  922.     if (filePath) {
  923.         free(filePath);
  924.     }
  925.     filePath = (char *)malloc(length + 1);
  926.     filePathLength = length;
  927.     }
  928.     strcpy(filePath, pathList);
  929.     stringPosition = filePath;
  930.     
  931.   /* the number of tabs + 1 equals the number of files dragged in */
  932.     files = 0;
  933.     while (stringPosition = index(stringPosition, '\t')) {
  934.       files++;
  935.       stringPosition++;
  936.     }
  937.     if ( files ) {
  938.     multipleFiles = YES;
  939.     } else {
  940.     multipleFiles = NO;
  941.     }
  942.     alreadyHaveIt  = NO;
  943.     nameEntering = filePath;
  944.     if ( nameEntering ) {
  945.     for ( idx=0; idx < [iconList count]; idx++ ) {
  946.         nameFromList = [[iconList objectAt:idx] filename];
  947.         if ( !strcmp(nameFromList,nameEntering) ) {
  948.         alreadyHaveIt = YES;
  949.         iconView = [iconList objectAt:idx];
  950.         break;
  951.         }
  952.     }
  953.     if ( !alreadyHaveIt ) {
  954.         [self addFileToScroller:
  955.         (char *)nameEntering:multipleFiles:iconWindowNum
  956.         ];
  957.         [iconView takeIconFromWindow:iconWindowNum
  958.                 :(float)iconX        :(float)iconY
  959.             :(float)iconWidth    :(float)iconHeight
  960.         ];
  961.         [[scroller docView] display];
  962.         // alreadyHaveIt = YES;
  963.         // NXDrawGrayBezel([[scroller docView] bounds], NULL);
  964.     }
  965.     }
  966.     return 0;
  967. }
  968.  
  969.  
  970. - (int)iconExitedAt:(double)x :(double)y
  971. {
  972.     int idx;
  973.     const char    *nameFromList;
  974.     
  975.     // if ( multipleFiles ) return 0;
  976.     if ( !alreadyHaveIt ) {
  977.     iconView = [iconList lastObject];
  978.     [self removeFileFromScroller:[iconView filename]]; 
  979.     [[scroller docView] display];
  980.     iconView = [iconList lastObject];
  981.     } else {
  982.     for ( idx=0; idx < [iconList count]; idx++ ) {
  983.         nameFromList = [[iconList objectAt:idx] filename];
  984.         if ( !strcmp(nameFromList,nameEntering) ) {
  985.         iconView = [iconList objectAt:idx];
  986.         break;
  987.         }
  988.     }
  989.     /***
  990.     [self perform:@selector(cut:)
  991.         with:self
  992.         afterDelay:1
  993.         cancelPrevious:YES
  994.     ];
  995.     ***/
  996.     // [self cut:self];
  997.     }
  998.     return 0;
  999. }
  1000.  
  1001.  
  1002. - updateIcon:sender;
  1003. {
  1004.     [self setFileIconFor:
  1005.     [iconList lastObject] :
  1006.     (char *)[[iconList lastObject] filename]
  1007.     ];
  1008.     return self;
  1009. }
  1010.  
  1011.  
  1012. - (int)iconReleasedAt:(double)x :(double)y ok:(int *)flag
  1013. {
  1014.     int idx;
  1015.     const char    *nameFromList;
  1016.     
  1017.     if ( alreadyHaveIt && (fromWhich!=NULL) ) {
  1018.     for ( idx=0; idx < [iconList count]; idx++ ) {
  1019.         nameFromList = [[iconList objectAt:idx] filename];
  1020.         if ( !strcmp(nameFromList,nameEntering) ) {
  1021.         iconView = [iconList objectAt:idx];
  1022.         break;
  1023.         }
  1024.     }
  1025.     [self slideIconInScroller: iconView toLocation:y];
  1026.     } else {
  1027.     // add to the list of permanently stored files
  1028.     [[scroller docView] display];
  1029.     [self perform:@selector(updateIcon:)
  1030.         with:self
  1031.         afterDelay:1
  1032.         cancelPrevious:NO
  1033.     ];
  1034.     }
  1035.     [self setSelected:iconView];
  1036.     [self writeFileList:listFileName];
  1037.     [self setFrom:NULL];
  1038.  
  1039.   /* accept the icon */
  1040.     *flag = 1;
  1041.  
  1042.     return 0;
  1043. }
  1044.  
  1045.  
  1046.  
  1047. /* instance methods */
  1048.  
  1049. - init
  1050. {
  1051.     char    appDirectory[1024], *lastSlash;
  1052.  
  1053.   /*
  1054.    * get our full path;  if it contains no slashes, we're being run from the
  1055.    * command line, so our current working directory's ok;  why are we worried
  1056.    * about the cwd?  well, we have to access our .o and .nib files and we use
  1057.    * relative pathnames to do so;  if our path contains a slash, use it to
  1058.    * figure out the directory we're executing from (should be from within a
  1059.    * file package)
  1060.    */
  1061.     strcpy(appDirectory, NXArgv[0]);
  1062.     lastSlash = rindex(appDirectory, '/');
  1063.     if (lastSlash) {
  1064.     *lastSlash = '\0';
  1065.       /* set our current working directory to be within the file package */
  1066.     chdir(appDirectory);
  1067.     }
  1068.     
  1069.     drawingView = emptyBox;
  1070.     
  1071.     return self;
  1072. }
  1073.     
  1074. - getFileInfo:sender
  1075. {
  1076.     id        speaker, last;
  1077.     char    *application, *fileType;
  1078.     int        anIlk, flag;
  1079.     char    *tiff;
  1080.     int        okFlag, length;
  1081.     FILE    *fd;
  1082.     int        rfd;
  1083.     char    tmpFile [ 128 ];
  1084.  
  1085.  
  1086.  
  1087.   /* ask the Workspace for information about the file */
  1088.     if ( filePath && strlen(filePath) ) {
  1089.     speaker = [NXApp appSpeaker];
  1090.     [speaker setSendPort:NXPortFromName(NX_WORKSPACEREQUEST, NULL)];
  1091.     [speaker getFileInfoFor: filePath
  1092.             app:&application
  1093.             type:&fileType
  1094.             ilk:&anIlk
  1095.             ok:&flag];
  1096.     
  1097.     last = [iconList lastObject];
  1098.     if ( !last ) return self;
  1099.     [last setAppOrFile : anIlk];
  1100.     if ( !([last hasIcon]) ) {
  1101.         [speaker getFileIconFor: filePath
  1102.         TIFF: &tiff
  1103.         TIFFLength: &length
  1104.         ok: &okFlag
  1105.         ];
  1106.         if ( okFlag ) {
  1107.         strcpy ( tmpFile, "/tmp/launchTMP123456.tiff" );
  1108.         NXGetTempFilename(tmpFile, 14);
  1109.         fd = fopen ( tmpFile, "w" );
  1110.         if ( fd ) {
  1111.             rfd = fileno ( fd );
  1112.             write ( rfd, tiff, length );
  1113.             close ( rfd );
  1114.             [last takeIconFromTIFF:tmpFile];
  1115.             unlink ( tmpFile );
  1116.         }
  1117.         }
  1118.     }
  1119.     }
  1120.     return self;
  1121. }
  1122.  
  1123. /****************************** infoPanel */
  1124. - infoPanel {
  1125.     if (!infoPanel) {
  1126.     [NXApp loadNibSection: "InfoPanel.nib" owner: self withNames:YES];
  1127.     // infoPanel = [InfoPanel new];
  1128.     }
  1129.     return infoPanel;
  1130. }
  1131.  
  1132. /****************************** displayInfoPanel */
  1133. - displayInfoPanel:sender
  1134. {
  1135.     if (!infoPanel) {
  1136.         [NXApp loadNibSection:"InfoPanel.nib" owner:self withNames:YES];
  1137.     // infoPanel = [InfoPanel new];
  1138.     }
  1139.     [infoPanel makeKeyAndOrderFront:self];
  1140.     
  1141.     return self;
  1142. }
  1143.  
  1144. /****************************** displayHelpPanel */
  1145. - displayHelpPanel:sender
  1146. {
  1147.     if (!helpPanel) {
  1148.         [NXApp loadNibSection:"HelpPanel.nib" owner:self withNames:NO];
  1149.     }
  1150.     [helpPanel makeKeyAndOrderFront:NULL];
  1151.     
  1152.     return self;
  1153. }
  1154.  
  1155. /****************************** displayPrefPanel */
  1156. - displayPrefPanel:sender
  1157. {
  1158.     if (!prefPanel) {
  1159.     [NXApp loadNibSection: "PrefPanel.nib" owner: self];
  1160.     }
  1161.     [prefPanel makeKeyAndOrderFront:NULL];
  1162.     
  1163.     return self;
  1164. }
  1165.  
  1166. /****************************** displayDock */
  1167. - displayDock:sender
  1168. {
  1169.     if ( dragPanel ) {
  1170.     [dragPanel makeKeyAndOrderFront:self];
  1171.     }
  1172.     return self;
  1173. }
  1174.  
  1175. - toggleFromButton:sender;
  1176. {
  1177.     [self toggleTextVisible:self];
  1178.     return self;
  1179. }
  1180.  
  1181.  
  1182. /****************************** toggleTextVisible */
  1183. - toggleTextVisible:sender
  1184. {
  1185.     NXSize screenSize;
  1186.     NXRect newPos;
  1187.     float maxX, deltaX;
  1188.     int weirdPosition;
  1189.     
  1190.     weirdPosition = NO;
  1191.     if ( textVisible ) {
  1192.     textVisible = NO;
  1193.     if ( oldPos.origin.x && oldPos.size.width ) {
  1194.         [dragPanel placeWindow: &oldPos];
  1195.     } else {
  1196.         // [dragPanel placeWindow: &onScreen];
  1197.     }
  1198.     [toggleTextMenu setTitle:
  1199.         [stringTable valueForStringKey:"toggleShow"]
  1200.     ];
  1201.     } else {
  1202.     textVisible = YES;
  1203.     [dragPanel getFrame: &oldPos];
  1204.     newPos.origin.x = oldPos.origin.x;
  1205.     newPos.origin.y = oldPos.origin.y;
  1206.     newPos.size.height = oldPos.size.height;
  1207.     newPos.size.width = oldPos.size.width;
  1208.     deltaX = widestName+ICON_DELTA+24+48 - oldPos.size.width;
  1209.     newPos.size.width += deltaX;
  1210.     [NXApp getScreenSize: &screenSize];
  1211.     maxX = newPos.origin.x + newPos.size.width;
  1212.     if ( maxX > screenSize.width - 66) {
  1213.         if ( maxX  - deltaX > screenSize.width - 66 ) {
  1214.         newPos.origin.x = screenSize.width - 66 - newPos.size.width;
  1215.         } else {
  1216.         newPos.origin.x -= deltaX;
  1217.         }
  1218.         weirdPosition = YES;
  1219.     }
  1220.     if ( newPos.origin.x <= 0.0 ) {
  1221.         newPos.origin.x = 0.0;
  1222.         weirdPosition = YES;
  1223.     }
  1224.     [dragPanel placeWindow: &newPos];
  1225.     [toggleTextMenu setTitle:
  1226.         [stringTable valueForStringKey:"toggleHide"]
  1227.     ];
  1228.     /***
  1229.     if ( (sender == self) && weirdPosition ) {
  1230.         [self perform:@selector(toggleTextVisible:)
  1231.         with:self
  1232.         afterDelay:600
  1233.         cancelPrevious:YES
  1234.         ];
  1235.     }
  1236.     ***/
  1237.     }
  1238.     return self;
  1239. }
  1240.  
  1241. /****************************** windowDidMove */
  1242. - windowDidMove:sender;
  1243. {
  1244.     NXRect tmpPos;
  1245.     if ( textVisible ) {
  1246.     [dragPanel getFrame: &tmpPos];
  1247.     oldPos.origin.x = tmpPos.origin.x;
  1248.     oldPos.origin.y = tmpPos.origin.y;
  1249.     }
  1250.     [dragPanel rememberPosition:self];
  1251.     return self;
  1252. }
  1253.  
  1254. /****************************** windowDidResize */
  1255. - windowDidResize:sender;
  1256. {
  1257.     [dragPanel rememberPosition:self];
  1258.     textVisible = NO;
  1259.     [toggleTextMenu setTitle:
  1260.     [stringTable valueForStringKey:"toggleShow"]
  1261.     ];
  1262.     return self;
  1263. }
  1264.  
  1265.  
  1266.  
  1267. @end